package com.jumaojiang.service;

import com.jumaojiang.exceptions.ResourceException;
import com.jumaojiang.mapper.*;
import com.jumaojiang.pojo.*;
import com.jumaojiang.utils.JWTUtil;
import com.jumaojiang.vo.QueryVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * javaee-rs
 *
 * @author wuhanwei
 * @version 1.0
 * @date 2021/11/8
 */
@Service
public class ResourceService {

    @Autowired
    private RsVideoMapper rsVideoMapper;

    @Autowired
    private FileUrlMapper fileUrlMapper;

    @Autowired
    private RsFileMapper rsFileMapper;

    @Autowired
    private ResourceGetTimeMapper resourceGetTimeMapper;

    // 属于用户的资源中间表
    @Autowired
    private FileResourceMapper fileResourceMapper;
    @Autowired
    private VideoResourceMapper videoResourceMapper;

    /**
     * 获取资源目录列表
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public Map<Integer, QueryVo> queryList(Integer userId) {
        // video
        RsVideoExample rsVideoExample = new RsVideoExample();
        RsVideoExample.Criteria criteria = rsVideoExample.createCriteria();
        criteria.andVideoIsDelEqualTo(0);
        List<RsVideo> rsVideos = rsVideoMapper.selectByExample(rsVideoExample);
        // videos进行排序
        Stream<RsVideo> sorted = rsVideos.stream().sorted((o1, o2) -> {
            String[] split1 = o1.getVideoUrl().split("/");
            String s1 = split1[split1.length - 1];
            String[] split2 = o2.getVideoUrl().split("/");
            String s2 = split2[split2.length - 1];
            int i1, i2;
            try {
                i1 = Integer.parseInt(s1);
                i2 = Integer.parseInt(s2);
            } catch (NumberFormatException e) {
                return -1;
            }
            return i1 - i2;
        });
        List<RsVideo> collectRsVideos = sorted.collect(Collectors.toList());
        // video user 中间表
//        VideoResourceExample videoResourceExample = new VideoResourceExample();
//        VideoResourceExample.Criteria criteria2 = videoResourceExample.createCriteria();
//        criteria2.andUserIdEqualTo(userId);
//        List<VideoResource> videoResources = videoResourceMapper.selectByExample(videoResourceExample);


        // file
        RsFileExample rsFileExample = new RsFileExample();
        RsFileExample.Criteria criteria3 = rsFileExample.createCriteria();
        criteria3.andFileIsDelEqualTo(0);
        List<RsFile> rsFiles = rsFileMapper.selectByExample(rsFileExample);
        for (RsFile rsFile : rsFiles) {
            FileUrlExample fileUrlExample = new FileUrlExample();
            FileUrlExample.Criteria criteria1 = fileUrlExample.createCriteria();
            criteria1.andRsFileIdEqualTo(rsFile.getFileId());
            rsFile.setFileUrlList(fileUrlMapper.selectByExample(fileUrlExample));
        }
        // file user 中间表
//        FileResourceExample fileResourceExample = new FileResourceExample();
//        FileResourceExample.Criteria criteria1 = fileResourceExample.createCriteria();
//        criteria1.andUserIdEqualTo(userId);
//        List<FileResource> fileResources = fileResourceMapper.selectByExample(fileResourceExample);

        // video and file
        Map<Integer, QueryVo> map = new HashMap<>();
        // 遍历video
        for (RsVideo rsVideo : collectRsVideos) {
            // 获取video中的chaid
            Integer chaId = rsVideo.getChaId();
            // 判断map集合是否存在相同chaId
            QueryVo queryVo = map.get(chaId);
            if (queryVo == null) {
                // 不存在,新添加
                queryVo = new QueryVo();
                queryVo.setChaId(chaId);
                map.put(chaId, queryVo);
            }
            // 重新封装新的对象
            QueryVo.ResourceVideo resourceVideo = new QueryVo.ResourceVideo();
            resourceVideo.setSectionTitle(rsVideo.getSectionTitle());
            resourceVideo.setVideoName(rsVideo.getVideoName());
            resourceVideo.setVideoId(rsVideo.getVideoId());
            // 权限控制, 该用户有权限再添加url和m3u8
//            if(videoResources.size() > 0){
//                for (VideoResource videoResource : videoResources) {
//                    if(videoResource.getVideoId().equals(rsVideo.getVideoId())){
//                        // 找到输入该用户的videoId, 添加资源
//                        resourceVideo.setVideoUrl(rsVideo.getVideoUrl());
//                        resourceVideo.setVideoM3u8(rsVideo.getVideoM3u8());
//                    }
//                }
//            }
            resourceVideo.setVideoUrl(rsVideo.getVideoUrl());
            resourceVideo.setVideoM3u8(rsVideo.getVideoM3u8());
            queryVo.getVideoList().add(resourceVideo);
        }
        // 遍历file
        for (RsFile rsFile : rsFiles) {
            // 获取file中的chaid
            Integer chaId = rsFile.getChaId();
            // 判断map集合是否存在相同chaId
            QueryVo queryVo = map.get(chaId);
            if (queryVo == null) {
                // 不存在,新添加
                queryVo = new QueryVo();
                queryVo.setChaId(chaId);
                map.put(chaId, queryVo);
            }
            // 重新封装新的对象
            QueryVo.ResourceFile resourceFile = new QueryVo.ResourceFile();
            resourceFile.setSectionTitle(rsFile.getSectionTitle());
            resourceFile.setFileName(rsFile.getFileName());
            resourceFile.setFileId(rsFile.getFileId());
            // 权限控制, 拥有权限再添加url
//            if(fileResources.size() > 0){
//                for (FileResource fileResource : fileResources) {
//                    if(fileResource.getFileId().equals(rsFile.getFileId())) {
//                        // 找到属于该用户的fileId, 添加资源
//                        List<String> urlList = resourceFile.getUrlList();
//                        for (FileUrl fileUrl : rsFile.getFileUrlList()) {
//                            urlList.add(fileUrl.getFileUrl());
//                        }
//                    }
//                }
//            }
            List<String> urlList = resourceFile.getUrlList();
            for (FileUrl fileUrl : rsFile.getFileUrlList()) {
                urlList.add(fileUrl.getFileUrl());
            }
            queryVo.getFileList().add(resourceFile);
        }
        return map;
    }

    /**
     * 用户查询次数减一
     * @param userId
     * @param type : 0:今日剩余获取次数 1:永久每日获取次数
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean userResourceDec(Integer userId, Integer type) throws ResourceException {
        ResourceGetTimeExample resourceGetTimeExample = new ResourceGetTimeExample();
        ResourceGetTimeExample.Criteria criteria = resourceGetTimeExample.createCriteria();
        // 添加用户id参数
        criteria.andUserIdEqualTo(userId);
        List<ResourceGetTime> resourceGetTimes = resourceGetTimeMapper.selectByExample(resourceGetTimeExample);
        if(resourceGetTimes.size() == 0) {
            // 服务器内部异常
            throw new ResourceException("服务器内部异常");
        }
        ResourceGetTime resourceGetTime = resourceGetTimes.get(0);
        Integer todayTime = resourceGetTime.getTodayTime();
        Integer everyDayTime = resourceGetTime.getEveryDayTime();
        if(type == 0){
            if(todayTime <= 0) {
                // TODO : 可抛全局异常: 今日次数已用光
                throw new ResourceException("今日次数已用光");
            }
            // 今日剩余获取次数减一
            resourceGetTime.setTodayTime(todayTime - 1);
        }else{
            if(everyDayTime <= 1) {
                // TODO : 可抛全局异常: 每日可获取次数至少保留1次
                throw new ResourceException("每日可获取次数至少保留1次");
            }
            // 永久每日获取次数减一
            resourceGetTime.setEveryDayTime(everyDayTime - 1);
        }
        // 更新表
        int i = resourceGetTimeMapper.updateByPrimaryKeySelective(resourceGetTime);
        if(i == 0){
            // 服务器内部异常 更新失败
            throw new ResourceException("更新失败");
        }
        return true;
    }

    /**
     * 用户查询次数加一
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean userResourceICN(Integer userId) throws ResourceException {
        // 获取询次数
        ResourceGetTimeExample resourceGetTimeExample = new ResourceGetTimeExample();
        ResourceGetTimeExample.Criteria criteria = resourceGetTimeExample.createCriteria();
        // 添加用户id参数
        criteria.andUserIdEqualTo(userId);
        List<ResourceGetTime> resourceGetTimes = resourceGetTimeMapper.selectByExample(resourceGetTimeExample);
        if(resourceGetTimes.size() == 0) {
            // 服务器内部异常
            throw new ResourceException("服务器内部异常");
        }
        ResourceGetTime resourceGetTime = resourceGetTimes.get(0);
        Integer todayTime = resourceGetTime.getTodayTime();
        Integer everyDayTime = resourceGetTime.getEveryDayTime();
        // 次数加一
        resourceGetTime.setTodayTime(todayTime + 1);
        resourceGetTime.setEveryDayTime(everyDayTime + 1);
        // 更新表
        int i = resourceGetTimeMapper.updateByPrimaryKeySelective(resourceGetTime);
        if(i == 0){
            // 服务器内部异常 更新失败
            throw new ResourceException("服务器内部异常");
        }
        return true;
    }

    /**
     * 查询次数减一更新 & 添加资源
     * @param request
     * @param fileId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean fileGet(HttpServletRequest request, Integer fileId, String isOwn) throws ResourceException {
        // 解析用户Id
        Integer userId = JWTUtil.parseUserId(request);
        // 添加资源到用户拥有资源中间表
        FileResource fileResource = new FileResource();
        fileResource.setFileId(fileId);
        fileResource.setUserId(userId);
        // 判断是获取还是永久兑换
        if(isOwn!=null && "true".equals(isOwn)){ // 永久兑换
            // 用户查询次数减一 (永久每日获取次数)
            if( !userResourceDec(userId, 1) ){
                // 全局异常: 服务器内部异常 更新失败
                throw new ResourceException("更新失败");
            }
            fileResource.setIsOwn(1);
        }else{
            // 用户查询次数减一 (今日获取次数)
            if( !userResourceDec(userId, 0) ){
                // 全局异常: 服务器内部异常 更新失败
                throw new ResourceException("更新失败");
            }
        }
        // 添加资源到用户拥有资源中间表
        int i1 = fileResourceMapper.insertSelective(fileResource);
        if(i1 == 0){
            // 全局异常: 服务器内部异常 添加资源到用户中间表失败
            throw new ResourceException("添加资源到用户中间表失败");
        }
        // 查询次数减一更新 and 添加资源成功
        return true;
    }

    /**
     * 查询次数减一更新 & 添加资源
     * @param request
     * @param videoId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean videoGet(HttpServletRequest request, Integer videoId, String isOwn) throws ResourceException {
        // 解析用户Id
        Integer userId = JWTUtil.parseUserId(request);
        // 添加资源到用户拥有资源中间表
        VideoResource videoResource = new VideoResource();
        videoResource.setVideoId(videoId);
        videoResource.setUserId(userId);
        // 判断是获取还是永久兑换
        if(isOwn!=null && "true".equals(isOwn)){ // 永久兑换
            // 用户查询次数减一 (永久每日获取次数)
            if( !userResourceDec(userId, 1) ){
                // 全局异常: 服务器内部异常 更新失败
                throw new ResourceException("更新失败");
            }
            // 添加永久拥有标识
            videoResource.setIsOwn(1);
        }else{
            // 用户查询次数减一 (今日获取次数)
            if( !userResourceDec(userId, 0) ){
                // 全局异常: 服务器内部异常 更新失败
                throw new ResourceException("更新失败");
            }
        }
        // 添加资源到用户拥有资源中间表
        int i = videoResourceMapper.insertSelective(videoResource);
        if(i == 0){
            // 全局异常: 服务器内部异常 添加资源到用户中间表失败
            throw new ResourceException("添加资源到用户中间表失败");
        }
        // 查询次数减一更新 and 添加资源成功
        return true;
    }

    /**
     * 通过主键查询file
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public RsFile queryFileById(Integer fileId){
        // 查询file
        RsFile rsFile = rsFileMapper.selectByPrimaryKey(fileId);
        // 查询fileUrl
        FileUrlExample fileUrlExample = new FileUrlExample();
        FileUrlExample.Criteria criteria1 = fileUrlExample.createCriteria();
        criteria1.andRsFileIdEqualTo(fileId);
        rsFile.setFileUrlList(fileUrlMapper.selectByExample(fileUrlExample));
        return rsFile;
    }

    /**
     * 通过主键查询video
     * @param videoId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public RsVideo queryVideoById(Integer videoId){
        return rsVideoMapper.selectByPrimaryKey(videoId);
    }

    /**
     * 获取用户查询次数
     * @param userId
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, readOnly = true)
    public ResourceGetTime queryGetTime(Integer userId){
        ResourceGetTimeExample resourceGetTimeExample = new ResourceGetTimeExample();
        ResourceGetTimeExample.Criteria criteria = resourceGetTimeExample.createCriteria();
        // 添加用户id参数
        criteria.andUserIdEqualTo(userId);
        List<ResourceGetTime> resourceGetTimes = resourceGetTimeMapper.selectByExample(resourceGetTimeExample);
        if(resourceGetTimes.size() > 0){
            return resourceGetTimes.get(0);
        }
        return null;
    }

    /**
     * 视频资源添加
     * @param rsVideo
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Integer videoAdd(HttpServletRequest request, RsVideo rsVideo) throws ResourceException {
        // 获取添加的用户id
        Integer userId = JWTUtil.parseUserId(request);
        // 添加资源
        if(rsVideo.getVideoUrl()==null || "".equals(rsVideo.getVideoUrl().trim())){
            return 0;
        }
        if(rsVideo.getVideoName()==null || "".equals(rsVideo.getVideoName().trim())){
            return 0;
        }
        if(rsVideo.getVideoM3u8()==null || "".equals(rsVideo.getVideoM3u8().trim())){
            return 0;
        }
        if(rsVideo.getSectionTitle()==null || "".equals(rsVideo.getSectionTitle().trim())){
            return 0;
        }
        if(rsVideo.getChaId() == null ){
            return 0;
        }
        rsVideo.setVideoCreateTime(new Date());
        rsVideo.setUserId(userId);
        // 查询视频是否重复
        RsVideoExample rsVideoExample = new RsVideoExample();
        RsVideoExample.Criteria criteria = rsVideoExample.createCriteria();
        criteria.andVideoUrlLike("%" + rsVideo.getVideoUrl() + "%");
        criteria.andVideoIsDelEqualTo(0);
        List<RsVideo> rsVideos = rsVideoMapper.selectByExample(rsVideoExample);
        if(rsVideos!=null && rsVideos.size()>0){
            // TODO : 全局异常视频重复
            throw new ResourceException("视频重复");
        }
        // 添加视频资源
        int i = rsVideoMapper.insertSelective(rsVideo);
        if(i == 0){
            // 让事务回滚
            throw new ResourceException("视频添加失败让事务回滚");
        }
        // 用户查询次数加一
        boolean b = userResourceICN(userId);
        if( !b ){
            // 让事务回滚
            throw new ResourceException("视频添加失败让事务回滚");
        }
        // 添加属于用户的资源中间表
        VideoResource videoResource = new VideoResource();
        videoResource.setIsOwn(1); // 永久拥有
        videoResource.setUserId(userId);
        videoResource.setVideoId(rsVideo.getVideoId());
        return videoResourceMapper.insertSelective(videoResource);
    }

    /**
     * 文件资源添加
     * @param request
     * @param rsFile
     * @return
     */
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public Integer fileAdd(HttpServletRequest request, RsFile rsFile) throws ResourceException {
        // 获取添加的用户id
        Integer userId = JWTUtil.parseUserId(request);
        // 添加资源
        if(rsFile.getFileName()==null || "".equals(rsFile.getFileName().trim())){
            return 0;
        }
        if(rsFile.getFileUrlList()==null || rsFile.getFileUrlList().size()==0){
            return 0;
        }
        if(rsFile.getSectionTitle()==null || "".equals(rsFile.getSectionTitle().trim())){
            return 0;
        }
        if(rsFile.getChaId() == null ){
            return 0;
        }
        // 添加文件资源
        rsFile.setUserId(userId);
        rsFile.setFileCreateTime(new Date());
        int i = rsFileMapper.insertSelective(rsFile);
        if(i == 0){
            //让事务回滚
            throw new ResourceException("添加文件资源失败让事务回滚");
        }
        // 添加文件对应的urls
        for (FileUrl fileUrl : rsFile.getFileUrlList()) {
            fileUrl.setRsFileId(rsFile.getFileId());
            int i1 = fileUrlMapper.insertSelective(fileUrl);
            if(i1 == 0){
                // 让事务回滚
                throw new ResourceException("添加文件资源失败让事务回滚");
            }
        }
        // 用户查询次数加一
        boolean b = userResourceICN(userId);
        if( !b ){
            // 让事务回滚
            throw new ResourceException("用户查询次数加一失败让事务回滚");
        }
        // 添加属于用户的资源中间表
        FileResource fileResource = new FileResource();
        fileResource.setIsOwn(1); // 永久拥有
        fileResource.setUserId(userId);
        fileResource.setFileId(rsFile.getFileId());
        return fileResourceMapper.insertSelective(fileResource);
    }




}
